<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>pomelo - Foryun - Share</title>
  <meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>

<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />

<meta name="theme-color" content="#f8f5ec" />
<meta name="msapplication-navbutton-color" content="#f8f5ec">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">


<meta name="author" content="Danic" /><meta name="description" content="pomelo构成 pomelo是由一个核心框架及一系列松耦合的模块构成，包括： 框架（Framework） 网络框架是pomelo最核心的部分 库（" /><meta name="keywords" content="Blog, IT, Share, Record" />






<meta name="generator" content="Hugo 0.81.0 with theme even" />


<link rel="canonical" href="http://foryun.com.cn/post/share/pomelo%E7%AE%80%E4%BB%8B/" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<link href="/sass/main.min.af7fd1da18d66c2b017df5b4cae508ef44cfcac3fb4c7c7a327fe4f4f9e28b08.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.1.20/dist/jquery.fancybox.min.css" integrity="sha256-7TyXnr2YU040zfSP+rEcz29ggW4j56/ujTPwjMzyqFY=" crossorigin="anonymous">


<meta property="og:title" content="pomelo" />
<meta property="og:description" content="pomelo构成 pomelo是由一个核心框架及一系列松耦合的模块构成，包括： 框架（Framework） 网络框架是pomelo最核心的部分 库（" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://foryun.com.cn/post/share/pomelo%E7%AE%80%E4%BB%8B/" /><meta property="article:section" content="post" />



<meta itemprop="name" content="pomelo">
<meta itemprop="description" content="pomelo构成 pomelo是由一个核心框架及一系列松耦合的模块构成，包括： 框架（Framework） 网络框架是pomelo最核心的部分 库（">

<meta itemprop="wordCount" content="5716">
<meta itemprop="keywords" content="pomelo," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="pomelo"/>
<meta name="twitter:description" content="pomelo构成 pomelo是由一个核心框架及一系列松耦合的模块构成，包括： 框架（Framework） 网络框架是pomelo最核心的部分 库（"/>

<!--[if lte IE 9]>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
<![endif]-->

<!--[if lt IE 9]>
  <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->

</head>
<body>
  <div id="mobile-navbar" class="mobile-navbar">
  <div class="mobile-header-logo">
    <a href="/" class="logo">Foryun</a>
  </div>
  <div class="mobile-navbar-icon">
    <span></span>
    <span></span>
    <span></span>
  </div>
</div>
<nav id="mobile-menu" class="mobile-menu slideout-menu">
  <ul class="mobile-menu-list">
    <a href="/">
        <li class="mobile-menu-item">Home</li>
      </a><a href="/post/">
        <li class="mobile-menu-item">Archives</li>
      </a><a href="/tags/">
        <li class="mobile-menu-item">Tags</li>
      </a><a href="/categories/">
        <li class="mobile-menu-item">Categories</li>
      </a><a href="/diary/">
        <li class="mobile-menu-item">Diary</li>
      </a><a href="/record/">
        <li class="mobile-menu-item">Record</li>
      </a><a href="/game/">
        <li class="mobile-menu-item">Game</li>
      </a><a href="/about/">
        <li class="mobile-menu-item">About</li>
      </a>
  </ul>

  


</nav>

  <div class="container" id="mobile-panel">
    <header id="header" class="header">
        <div class="logo-wrapper">
  <a href="/" class="logo">Foryun</a>
</div>





<nav class="site-navbar">
  <ul id="menu" class="menu">
    <li class="menu-item">
        <a class="menu-item-link" href="/">Home</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/post/">Archives</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/tags/">Tags</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/categories/">Categories</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/diary/">Diary</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/record/">Record</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/game/">Game</a>
      </li><li class="menu-item">
        <a class="menu-item-link" href="/about/">About</a>
      </li>
  </ul>
</nav>

    </header>

    <main id="main" class="main">
      <div class="content-wrapper">
        <div id="content" class="content">
          <article class="post">
    
    <header class="post-header">
      <h1 class="post-title">pomelo</h1>

      <div class="post-meta">
        <span class="post-time"> 0001-01-01 </span>
        <div class="post-category">
            <a href="/categories/share/"> Share </a>
            </div>
          <span class="more-meta"> 约 5716 字 </span>
          <span class="more-meta"> 预计阅读 12 分钟 </span>
        <span id="busuanzi_container_page_pv" class="more-meta"> <span id="busuanzi_value_page_pv"><img src="/img/spinner.svg" alt="spinner.svg"/></span> 次阅读 </span>
      </div>
    </header>

    <div class="post-toc" id="post-toc">
  <h2 class="post-toc-title">文章目录</h2>
  <div class="post-toc-content always-active">
    <nav id="TableOfContents">
  <ul>
    <li>
      <ul>
        <li><a href="#pomelo构成">pomelo构成</a></li>
        <li><a href="#术语">术语</a></li>
        <li><a href="#pomelo-特点及定位">Pomelo 特点及定位</a></li>
      </ul>
    </li>
  </ul>
</nav>
  </div>
</div>
    <div class="post-content">
      <h2 id="pomelo构成">pomelo构成</h2>
<p>pomelo是由一个核心框架及一系列松耦合的模块构成，包括：</p>
<ul>
<li>框架（Framework）
<ul>
<li>网络框架是pomelo最核心的部分</li>
</ul>
</li>
<li>库（Libraries）
<ul>
<li>pomelo提供了很多的库。其中有些是和游戏逻辑相关的，如：AI、AOI、路径查找等；也有一些通用功能库，如：定时任务、数据同步等。</li>
</ul>
</li>
<li>工具（Tools）
<ul>
<li>pomelo提供了很多工具，包括服务器管理&amp;控制工具、命令行工具（如：pomelo list、pomelo kill、pomelo stop）、压力测试工具等。</li>
</ul>
</li>
<li>客户端SDK（Client SDKs）
<ul>
<li>pomelo为大多数平台提供了客户端SDK，包括：JavaScript、C、C#、Android、IOS、以及Unity3D。pomelo的通讯协议是开放且可自定义的，开发者可以轻易的定义他们自己的通讯协议，这样pomelo就可以扩展支持所有客户端。</li>
</ul>
</li>
<li>Demo
<ul>
<li>pomelo官方提供了几个Demo，开发者可以通过这些事例了解pomelo的运行机制，并可以快速上手使用：
<ul>
<li><a href="https://github.com/NetEase/chatofpomelo">Chat of Pomelo</a>：一个聊天室示例，可以运行于大多数平台。示例中包含了<code>channel</code>、多<code>connector</code>服务端等 Pomelo 特性的演示</li>
<li><a href="https://github.com/NetEase/treasures">Treasures</a>：一个简单的游戏示例及HTML5客户端</li>
<li><a href="http://pomelo.netease.com/lordofpomelo/">Lord of Pomelo</a>：基于HTML5的一个完整的 MMO 游戏示例</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="术语">术语</h2>
<p>pomelo制定了灵活的服务器扩展机制，在pomelo中包含Master、Connector、Gate、Application四类服务器。</p>
<ul>
<li>
<p>Master（主服务器）</p>
<ul>
<li>主服务器负责加载配置文件，通过配置文件服务器启动集群，并对所有服务器进行管理。</li>
</ul>
</li>
<li>
<p>Gate</p>
<ul>
<li>大多数情况下，Gate服务器不参与RPC调用。在pomelo服务器配置项中，Gate服务器仅需要一个客户端口配置（即clientPort），其作用中是提供前端负载均衡。</li>
<li>理想情况下，Gate服务器会是客户端的第一个连接点，连接后Gate服务器给客户端Connector服务器。Gate服务器实现负载均衡时，会通过客户端的标识值（Key、ID等）做Hash运算，然后得到客户端所需要连接的Connector服务器。</li>
</ul>
</li>
<li>
<p>Connector（连接服务器）</p>
<ul>
<li>Connector负责接收连接请求，创建客户端连接，维护客户端的Session信息，接收客户端请求、并根据路由配置策略将请求定向到具体的后端业务服务器。</li>
<li>后端服务器处理完成后或需要向客户端推送消息时，Connector服务器还需要作为一个中间角色向客户端发送消息。</li>
<li>Connector服务器会同时拥有前端端口（clientPort）和后端端口（port）。其中，客户端端口用于监听客户端连接，而后端端口用于和向其他后端服务器的通讯。</li>
</ul>
</li>
<li>
<p>Application（应用逻辑服务器）</p>
<ul>
<li>Gate服务器和Connector服务器称为“前端服务器”，而应用服务器被称为后端服务器，其用于实现应用逻辑并向客户端提供应用逻辑服务。Application服务器的客户端请求来源于前端服务器，两者之间交互通过RPC调用实现。理论上讲，后端服务器不会与前端服务器直接通讯，因此只需要定义一个用于提供服务器的后端端口即可。</li>
</ul>
</li>
<li>
<p>RPC调用</p>
<ul>
<li>pomelo通过RPC调用实现进程间的通讯。这些内部RPC调用有以下三种方式：
<ul>
<li>前端服务器的客户端请求转发到后端服务器</li>
<li>后端服务器讲session信息推送到请求信息的前端服务器</li>
<li>后端服务器通过channel向前端服务器推送信息</li>
</ul>
</li>
<li>以上三类RPC调用属于系统RPC，除RPC调用外，用户还可以自定义RPC调用。自定义时，需要用户编写RPC服务器的remote及handler代码。</li>
</ul>
</li>
<li>
<p>Route、Router</p>
<ul>
<li>route是服务端点的唯一标识符，标识客户端向服务器推送信息，或客户端接收来自服务器数据的路径。</li>
<li>对于服务端来说，通常遵守以.分割的命名方式，如：chat.chatHandler.send，其中：chat表示接收信息的服务器，chatHandler是服务器中定义的一个处理器（Handler），而send表示处理器中的一个处理方法。</li>
<li>对于客户端来说，通常使用on[ExpectedEventName]命名方式，如：onChat。客户端可以为路由指定一个处理函数，当服务器推送消息时，客户端会收到回调。</li>
<li>一般来说，运行应用的服务器会同时有多个，当用户端请求达到前端服务器后，会分发到一个具体的后端服务器，这种分发需要一个路由函数router。router会根据用户session及其请求的内容做一些运算，并将其映到一台具体的服务器ID。</li>
<li>可以通过应用的route来电泳配置给某累服务器配置的router，如果不配置时，pomelo会使用默认的router。默认router是使用session中的uid做crc32校验，然后使用检验码作为key，再跟同类型应用服务器数取余，即可得到路由要使用的服务器编号。这样也会有问题，当session没有绑定uid时，这是uid字段会是undefined，这回造成所有的请求都路由到同一服务器。所以在实际开发中，还是需要自己来配置router的。</li>
</ul>
</li>
<li>
<p>Session</p>
<ul>
<li>
<p>pomelo中有三种session，还有两种session服务。三种session分别是：Session、FrontendSession、BackendSession。两种Session服务器是：SessionService、BackendSessionService。这点是令人疑惑的，简单介绍如下。</p>
</li>
<li>
<p><strong><code>Session</code></strong></p>
<p><code>Session</code>是对一个客户端连接的抽象，其字段类似如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-javascript" data-lang="javascript"><span class="p">{</span>
  <span class="nx">id</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">session</span> <span class="nx">id</span><span class="o">&gt;</span> <span class="c1">// readonly
</span><span class="c1"></span>  <span class="nx">frontendId</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">frontend</span> <span class="nx">server</span> <span class="nx">id</span><span class="o">&gt;</span> <span class="c1">// readonly
</span><span class="c1"></span>  <span class="nx">uid</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">bound</span> <span class="nx">uid</span><span class="o">&gt;</span> <span class="c1">// readonly
</span><span class="c1"></span>  <span class="nx">settings</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">key</span><span class="o">-</span><span class="nx">value</span> <span class="nx">map</span><span class="o">&gt;</span> <span class="c1">// read and write  
</span><span class="c1"></span>  <span class="nx">__socket__</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">raw_socket</span><span class="o">&gt;</span>
  <span class="nx">__state__</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">session</span> <span class="nx">state</span><span class="o">&gt;</span>
    
  <span class="c1">// ...
</span><span class="c1"></span><span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><ul>
<li><code>id</code>：这个 session 的<code>id</code>，全局唯一，一般使用自增的方式生成</li>
<li><code>frontendId</code>：这个 session 所对应的前端服务器的<code>id</code></li>
<li><code>uid</code>：这个 session 所绑定的用户的 <code>id</code></li>
<li><code>settings</code>：一个<code>key-value</code> map，用于保存一些 session 的自定义属性。如，聊天室中的房间号就可以做为一个 session 的自定义属笥</li>
<li><code>__socket__</code>：对原生 <code>socket</code>的引用</li>
<li><code>__state__</code>：用于指明 session 的当前状态</li>
</ul>
<p>从以上可以看出，session 一旦建立，其<code>id</code>、<code>frontendId</code>、<code>uid</code>、<code>__socket__</code>、<code>__state__</code>字段就都是确定的，且是只读的。而<code>settings</code>也不应该被随意的修改。</p>
<p>也因此，在前端服务器中引入了<code>FrontendSession</code>，它可以被看做是真实 session 在前端服务器中的一个副本。</p>
<p><strong><code>FrontendSession</code>与<code>SessionService</code></strong></p>
<p><code>FrontendSession</code>字段结构大致如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-javascript" data-lang="javascript"><span class="p">{</span>
  <span class="nx">id</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">session</span> <span class="nx">id</span><span class="o">&gt;</span> <span class="c1">// readonly
</span><span class="c1"></span>  <span class="nx">frontendId</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">frontend</span> <span class="nx">server</span> <span class="nx">id</span><span class="o">&gt;</span> <span class="c1">// readonly
</span><span class="c1"></span>  <span class="nx">uid</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">bound</span> <span class="nx">uid</span><span class="o">&gt;</span> <span class="c1">// readonly
</span><span class="c1"></span>  <span class="nx">settings</span> <span class="o">:</span> <span class="o">&lt;</span><span class="nx">key</span><span class="o">-</span><span class="nx">value</span> <span class="nx">map</span><span class="o">&gt;</span> <span class="c1">// read and write  
</span><span class="c1"></span><span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><p><code>FrontendSession</code>功能如下：</p>
<ul>
<li><code>settings</code>字段可以通过<code>FrontendSession</code>来设置，而且其值可以通过调用<code>push</code>方法同步到原实 <code>Session</code> 中。</li>
<li>通过调用<code>FrontendSession</code>的<code>bind</code>方法，可以将<code>uid</code>绑定到<code>Session</code>。</li>
<li><code>Session</code>中的只读字段也可以通过<code>FrontendSession</code>，但是对<code>FrontendSession</code>中与<code>Session</code>相同字段进行修改时，并不会反应到原始<code>Session</code>。</li>
</ul>
<p><code>SessionService</code>用于维护所有原始<code>Session</code>，包括：只读字段、绑定<code>uid</code>及用户自定义字段。</p>
<p><strong><code>BackendSession</code>与<code>BackendSessionService</code></strong></p>
<p><code>BackendSession</code>与<code>FrontendSession</code>类似，其字段也与<code>FrontendSession</code>基本一致，不同的是其用于后端服务器。</p>
<p><code>BackendSession</code>是由<code>BackendSessionService</code>创建和维护的。在后端服务器收到请求后，<code>BackendSessionService</code>会根据前端服务器的<code>rpc</code>参数创建<code>BackendSession</code>。</p>
<p>同样的，对<code>BackendSession</code>的中字段的修改也不会反应到原始<code>Session</code>中。与<code>FrontendSession</code>一样，<code>BackendSession</code>中也有<code>bind</code>、<code>unbind</code>、<code>push</code>方法，用于绑定/解绑<code>uid</code>或修改<code>settings</code>中的字段值等。不同的是<code>BackendSession</code>实际上是以<code>sys</code>命名空间发起的远程调用。</p>
</li>
</ul>
</li>
<li>
<p>Channel</p>
<ul>
<li>Channel可以看做是玩家的容器，主要用于需要频繁广播推送消息的场景。当向一个Channel推送消息时，加入到这个Channel中的所有玩家都会收到广播的消息。玩家可以加入到多个Channel中，然后就可以收到所有加入的Channel的广播消息。</li>
<li>需要注意的是，Channel是服务器-本地模式，这意味着应用服务器A与B不会共享Channel信息，也就不能收到其他服务器所发送的消息。</li>
</ul>
</li>
<li>
<p>消息类型：Request、Response、Notify、Push</p>
<ul>
<li>pomelo与客户通过消息进行交互，pomelo中有4种消息类型，分别是：Request、Response、Notify、Push。
<ul>
<li>request-response交互：客户端发起Request到服务端，服务端处理完成后，会给其返回Response。</li>
<li>notify交互：Notify同样是客户端向服务器发送消息，但不需要服务器的回复。</li>
<li>Push交互：Push是服务端主动发送给客户端的消息，客户端可以通过监听制定的路由实现服务端主动推送消息的接收。</li>
</ul>
</li>
</ul>
</li>
<li>
<p>Filter</p>
<ul>
<li>pomelo中的Filter（筛选器）分为两类：before filter和after filter。Before filter会对请求做一些前置处理，如：检查玩家是否已登录、统计记录等。而after filter会对请求做一些后置处理，如：释放请求上下文的资源、记录请求耗时信息等。在after filter中不应该在对响应内容做修改，因为在进入after filter之前响应就发送给客户端。</li>
<li>每类filter都可以注册多个，从而形成一个filter链，所有请求都会经过每个filter的统一处理。</li>
</ul>
</li>
<li>
<p>Handler</p>
<ul>
<li>Handler（处理器）是实现业务逻辑的地方，在请求处理链中Handler位于before filter和after filter之间。其定义形式类似如下：</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-javascript" data-lang="javascript">  <span class="nx">handler</span><span class="p">.</span><span class="nx">methodName</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="nx">session</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...
</span><span class="c1"></span>  <span class="p">}</span>
</code></pre></td></tr></table>
</div>
</div><p><code>Handler</code>参数与<code>before filter</code>类似。<code>Handler</code>处理完成后，如果需要向客户返回响应信息，可以将响应内容包装成JavaScript对象，并通过<code>next</code>传递给后面的流程。</p>
</li>
<li>
<p>Component</p>
<p>Pomelo 框架是由若干松散耦合的组件（<code>Component</code>）构成的，而每个组件会分别完成一些功能，事实上 Pomelo 的核心功能都是由组件完成的。Pomelo 框架可以看做是组件的容器，会完成组件的加载及组件生命周期的管理。每个组件都定义了<code>start</code>、<code>afterStart</code>、<code>stop</code>等回调函数，用于完成组件生命周期的管理。</p>
</li>
<li>
<p>Plugin</p>
<ul>
<li><code>Plugin</code>（插件）是另一种扩展机制，它自 Pomelo 0.6 版本中引入。<code>Plugin</code>由多个<code>Component</code>及一些事件处理器（用于处理框架发送的事件）组成。<code>Plugin</code>为 Pomelo 提供了一种更加灵活的扩展机制，它不仅提供了组件相关功能，还可以对框架的全局事件做出响应。</li>
</ul>
</li>
<li>
<p>Admin client、Monitor、Master</p>
<ul>
<li>在pomelo的管理框架中，服务器会有三种角色：Admin client、Monitor、Master。各功能如下：
<ul>
<li>Master-Master负责收集服务器集群信息，对服务器集群进行管理等。Master还会接收Admin client的请求，并按请求命令执行相应的操作，如：查询服务器状态、向集群中增加服务器等。</li>
<li>Monitor-Monitor运行于各个服务器当中，它会向Master进行注册，并将服务器状态上报给Master。炳辉根据Master发来的消息，对服务器进行更新。</li>
<li>Admin client-是一个第三方管理客户端。它会连接并注册到Master，它可以查询服务器集群信息、或向Master发送命令实现对集群的管理。</li>
</ul>
</li>
</ul>
</li>
<li>
<p>Admin module</p>
<ul>
<li>
<p>在 Pomelo 中<code>module</code>特指服务器的监控管理模块，它类似于<code>Component</code>，但它实现的是监控相关逻辑，如进程状态收集等。</p>
<p>用户使用<code>Admin module</code>用于服务器进行管理时，可以通过<code>application</code>的<code>registerAdmin</code>注册管理模块。每个管理模式都会定义以下四种回调函数，每种回调都是可选的：</p>
<ul>
<li><code>masterHandler(agent, msg, cb)</code> - 当收到<code>Monitor</code>的<code>request/notify</code>数据时，Master会进行回调，并完成应用服务器的消息处理。</li>
<li><code>monitorHandler(agent, msg, cb)</code> - 当收到<code>Master</code>的<code>request/notify</code>数据时，<code>Monitor</code>会进行回调，并完成相应数据处理</li>
<li><code>clientHandler(agent, msg, cb),</code> - 当收到第三方客户端的<code>request/notify</code>数据时，<code>Monitor</code>会进行回调</li>
<li><code>start(cb)</code> - 当<code>Admin module</code>注册完成后，会由框架进行回调，以完成一些初始化工作</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="pomelo-特点及定位">Pomelo 特点及定位</h2>
<ul>
<li>
<p>为什么选择 Pomelo</p>
<ul>
<li>
<p>高并发、实时游戏服务器的开发是一项非常复杂的工作。一套好的开发框架可以大大减少游戏开发的复杂性、提高开发效率。而 Pomelo 就一款非常好的开源、高性能、高并发游戏服务器解决方案，它具有以下特点：</p>
<ul>
<li>
<p>可伸缩性架构</p>
<p>Pomelo 采用单线程多进程架构，每个服务器本身都是一个Node进程。通过修改配置文件，可以很轻松的向现有服务器集群中添加或删除服务器，而不需要对源码做任何修改。</p>
</li>
<li>
<p>易用</p>
<p>Pomelo 基于Node.js开发，其开发模式类似于 Web 开发（如，<a href="https://itbilu.com/nodejs/npm/EJUJrGVsg.html">Express</a>）。Pomelo 遵从<code>'convention over configuration'</code>的原则，几乎零配置就可以得到一个基本的可运行应用。</p>
</li>
<li>
<p>弱耦合及可扩展</p>
<p>基于Node.js的微模块原则，Pomelo 本身只有很少的代码，所有的<code>Componet</code>、<code>库</code>、<code>工具</code>都可以通过<code>npm</code>模块的形式扩展进来。所有第三方都可以开发自己的模块，并整合到 Pomelo 中。</p>
</li>
<li>
<p>完成的文档及Demo</p>
<p>在<a href="https://github.com/NetEase/pomelo/wiki">Pomelo Wiki</a>中提供了完整的中英文档。除简单Demo外，还提供了一个完整的MMO游戏<a href="http://pomelo.netease.com/lordofpomelo/">Lordofpomelo</a>（<a href="https://github.com/NetEase/lordofpomelo">源码</a>），以供开发者借鉴和参考。</p>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p>Pomelo 定位</p>
<ul>
<li>Pomelo 是一个轻量级的服务器端游戏应用框架，其非常适用于如：实时游戏、社交游戏、移动游戏等。但不推荐将 Pomelo 用于开发大型MMORPG游戏服务器，尤其是大型3D游戏。</li>
</ul>
</li>
</ul>

    </div>

    <div class="post-copyright">
  <p class="copyright-item">
    <span class="item-title">文章作者</span>
    <span class="item-content">Danic</span>
  </p>
  <p class="copyright-item">
    <span class="item-title">上次更新</span>
    <span class="item-content">
        0001-01-01
        
    </span>
  </p>
  
  
</div>
<footer class="post-footer">
      <div class="post-tags">
          <a href="/tags/pomelo/">pomelo</a>
          </div>
      <nav class="post-nav">
        <a class="prev" href="/post/record/git%E5%B7%A5%E4%BD%9C%E6%B5%81/">
            <i class="iconfont icon-left"></i>
            <span class="prev-text nav-default">Git工作流</span>
            <span class="prev-text nav-mobile">上一篇</span>
          </a>
        
      </nav>
    </footer>
  </article>
        </div>
        

  <span id="/post/share/pomelo%E7%AE%80%E4%BB%8B/" class="leancloud_visitors" data-flag-title="pomelo">
		<span class="post-meta-item-text">文章阅读量 </span>
		<span class="leancloud-visitors-count">0</span>
		<p></p>
	  </span>
  <div id="vcomments"></div>
  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src='//unpkg.com/valine/dist/Valine.min.js'></script>
  <script type="text/javascript">
    new Valine({
        el: '#vcomments' ,
        appId: 'insXINA0D2ccQdcEfEcMSjgn-gzGzoHsz',
        appKey: 'HEAEkloDNn3aFg4Yr1W4iGM3',
        notify:  false ,
        verify:  false ,
        avatar:'mm',
        placeholder: '说点什么吧...',
        visitor:  true 
    });
  </script>

  

      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="social-links">
      <a href="mailto:1186976350@qq.com" class="iconfont icon-email" title="email"></a>
      <a href="https://github.com/DanicCheng" class="iconfont icon-github" title="github"></a>
      <a href="https://space.bilibili.com/2920221?spm_id_from=333.788.b_765f7570696e666f.2" class="iconfont icon-bilibili" title="bilibili"></a>
  
</div>

<div class="copyright">
  <span class="power-by">
    由 <a class="hexo-link" href="https://gohugo.io">Hugo</a> 强力驱动
  </span>
  <span class="division">|</span>
  <span class="theme-info">
    主题 - 
    <a class="theme-link" href="https://github.com/olOwOlo/hugo-theme-even">Even</a>
  </span>

  <div class="busuanzi-footer">
    <span id="busuanzi_container_site_pv"> 本站总访问量 <span id="busuanzi_value_site_pv"><img src="/img/spinner.svg" alt="spinner.svg"/></span> 次 </span>
      <span class="division">|</span>
    <span id="busuanzi_container_site_uv"> 本站总访客数 <span id="busuanzi_value_site_uv"><img src="/img/spinner.svg" alt="spinner.svg"/></span> 人 </span>
  </div>

  <span class="copyright-year">
    &copy; 
    2017 - 
    2021<span class="heart"><i class="iconfont icon-heart"></i></span><span>Foryun</span>
  </span>

  <span class="beian">
    
    备案号：<a href="https://beian.miit.gov.cn" target="_blank">粤ICP备18045119号</a>
    
  </span>

</div>

    </footer>

    <div class="back-to-top" id="back-to-top">
      <i class="iconfont icon-up"></i>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/slideout@1.0.1/dist/slideout.min.js" integrity="sha256-t+zJ/g8/KXIJMjSVQdnibt4dlaDxc9zXr/9oNPeWqdg=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.1.20/dist/jquery.fancybox.min.js" integrity="sha256-XVLffZaxoWfGUEbdzuLi7pwaUJv1cecsQJQqGLe7axY=" crossorigin="anonymous"></script>



<script type="text/javascript" src="/js/main.min.c99b103c33d1539acf3025e1913697534542c4a5aa5af0ccc20475ed2863603b.js"></script>

<script id="baidu_analytics">
  var _hmt = _hmt || [];
  (function() {
    if (window.location.hostname === 'localhost') return;
    var hm = document.createElement("script"); hm.async = true;
    hm.src = "https://hm.baidu.com/hm.js?57ed19d6fdd95893edd119b86ac49dab";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
  })();
</script>

<script id="baidu_push">
  (function(){
    if (window.location.hostname === 'localhost') return;
    var bp = document.createElement('script'); bp.async = true;
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
      bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
    }
    else {
      bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
  })();
</script>




</body>
</html>
